home *** CD-ROM | disk | FTP | other *** search
/ Info-Mac 4 / Info_Mac IV CD-ROM (Pacific HiTech Inc.)(August 1994).iso / Development / Source / MSG Demo 1.4.source Folder / Demo ƒ / Shell ƒ / prefs.c < prev    next >
Text File  |  1994-04-15  |  13KB  |  454 lines

  1. /**********************************************************************\
  2.  
  3. File:        prefs.c
  4.  
  5. Purpose:    This module handles creating/opening/closing/updating
  6.             the preference file, and copying the preference file
  7.             data into application globals (and back).
  8.  
  9. This program is free software; you can redistribute it and/or modify
  10. it under the terms of the GNU General Public License as published by
  11. the Free Software Foundation; either version 2 of the License, or
  12. (at your option) any later version.
  13.  
  14. This program is distributed in the hope that it will be useful,
  15. but WITHOUT ANY WARRANTY; without even the implied warranty of
  16. MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  17. GNU General Public License for more details.
  18.  
  19. You should have received a copy of the GNU General Public License
  20. along with this program in a file named "GNU General Public License".
  21. If not, write to the Free Software Foundation, 675 Mass Ave,
  22. Cambridge, MA 02139, USA.
  23.  
  24. \**********************************************************************/
  25.  
  26. #include "prefs.h"
  27. #include "dialogs.h"
  28. #include "environment.h"
  29. #include "util.h"
  30. #include "sounds.h"
  31. #include "program globals.h"
  32. #include "Folders.h"
  33.  
  34. #define        PREFS_FILE_NAME            "\pMSG Demo prefs"
  35. #define        PREFS_TYPE                'PREF'
  36. // CREATOR is #defined in "program globals.h"
  37. #define        PREFS_HEADER_VERSION    2
  38.  
  39. Boolean        gCanSavePrefs;
  40. Str255        gMyName;
  41. Str255        gMyOrg;
  42.  
  43. typedef struct
  44. {
  45.     char            regname[40];
  46.     char            regorg[40];
  47.     unsigned char    sound;
  48.     unsigned char    isreversed;
  49.     unsigned char    isfirstpict;
  50.     unsigned char    unused;
  51.     int                lastwipe;
  52.     int                wipestatus;
  53.     long            fileID;
  54. } PrefStruct;
  55.  
  56. enum        /* possible error codes */
  57. {
  58.     prefs_allsWell=0,                /* no error */
  59.     prefs_diskReadErr,                /* error reading prefs file */
  60.     prefs_diskWriteErr,                /* error writing prefs file */
  61.     prefs_cantOpenPrefsErr,            /* error trying to open prefs file */
  62.     prefs_cantCreatePrefsErr,        /* error trying to create new prefs file */
  63.     prefs_noMorePrefsErr,            /* no more prefs found in prefs file */
  64.     prefs_versionNotSupportedErr,    /* prefs file created by later version of program */
  65.     prefs_virginErr,                /* prefs file didn't exist -- first time running */
  66.     prefs_IDNotMatchErr                /* file ID in current prefs doesn't match program's ID */
  67. };
  68.  
  69. /* internal globals for use in prefs.c only */
  70. static long            gFileID;
  71. static Boolean        gCanSavePrefs;
  72. static PrefStruct    thePrefs;
  73. static long            gPrefsFilePos;
  74.  
  75. /*-----------------------------------------------------------------------------------*/
  76. /* internal stuff for prefs.c                                                        */
  77.  
  78. int OpenPrefsFile(int *prefsFileID);
  79. int SetupNewPrefsFile(int prefsFileID);
  80. void ClosePrefsFile(int prefsFileID);
  81. int GetNextPrefs(int prefsFileID);
  82. int SavePrefs(int prefsFileID);
  83. int CheckVersion(int prefsFileID);
  84. int GetFileID(void);
  85. int CheckFileID(void);
  86. int Virgin(int prefsFileID);
  87. void DefaultPrefs(void);
  88. void CopyGlobalsToPrefs(void);
  89. void CopyPrefsToGlobals(void);
  90. void GetRegistration(void);
  91.  
  92. void SaveThePrefs(void)
  93. /* standard procedure callable from anywhere to save prefs to disk (if possible) */
  94. {
  95.     int            prefsFileID;
  96.     
  97.     if (gCanSavePrefs)        /* if we had no errors in PreferencesInit() */
  98.     {
  99.         OpenPrefsFile(&prefsFileID);    /* open the prefs file */
  100.         CopyGlobalsToPrefs();            /* copy global variables to prefs struct */
  101.         SavePrefs(prefsFileID);            /* save prefs to disk */
  102.         ClosePrefsFile(prefsFileID);    /* close prefs file */
  103.     }
  104. }
  105.  
  106. int PreferencesInit(void)
  107. {
  108.     int                prefsFileID;
  109.     int                err;
  110.     
  111.     gCanSavePrefs=FALSE;    /* assume the worst and maybe you'll be pleasantly surprised */
  112.     err=GetFileID();        /* get application file ID */
  113.     if (err!=prefs_allsWell)    /* screwed up already?!? */
  114.         return err;
  115.     
  116.     err=OpenPrefsFile(&prefsFileID);    /* open prefs file (or create new one) */
  117.     if (err!=prefs_allsWell)
  118.     {
  119.         if ((err==prefs_diskReadErr) || (err==prefs_diskWriteErr) || (err==prefs_virginErr))
  120.             ClosePrefsFile(prefsFileID);    /* close & abort if error or if new prefs */
  121.         return err;
  122.     }
  123.     
  124.     err=CheckVersion(prefsFileID);        /* check prefs version */
  125.     if (err!=prefs_allsWell)
  126.     {
  127.         ClosePrefsFile(prefsFileID);
  128.         return err;
  129.     }
  130.     
  131.     GetFPos(prefsFileID, &gPrefsFilePos);
  132.     gPrefsFilePos-=sizeof(thePrefs);
  133.     do
  134.     {
  135.         gPrefsFilePos+=sizeof(thePrefs);
  136.         err=GetNextPrefs(prefsFileID);        /* get prefs struct from file */
  137.         if (err==prefs_noMorePrefsErr)        /* or not */
  138.             return (Virgin(prefsFileID));    /* can't find our file ID, it's our first time */
  139.         
  140.         if (err!=prefs_allsWell)            /* any other error, just abort */
  141.         {
  142.             ClosePrefsFile(prefsFileID);
  143.             return err;
  144.         }
  145.         
  146.         err=CheckFileID();                    /* check file ID of current prefs struct */
  147.     }
  148.     while (err==prefs_IDNotMatchErr);
  149.     
  150.     CopyPrefsToGlobals();                    /* copy prefs struct to program globals */
  151.     ClosePrefsFile(prefsFileID);            /* close prefs file */
  152.     
  153.     return prefs_allsWell;                    /* piece o' cake */
  154. }
  155.  
  156. void PrefsError(int err)
  157. {
  158.     Str255            tempStr;
  159.     
  160.     switch (err)
  161.     {
  162.         case prefs_diskReadErr:
  163.         case prefs_diskWriteErr:
  164.         case prefs_cantCreatePrefsErr:
  165.         case prefs_cantOpenPrefsErr:
  166.         case prefs_versionNotSupportedErr:
  167.             DefaultPrefs();                    /* use default prefs if error */
  168.             gCanSavePrefs=FALSE;            /* don't bother trying to save prefs later */
  169.             GetIndString(tempStr, 128, err);    /* get error string from .rsrc file */
  170.             ParamText(tempStr, "\p", "\p", "\p");
  171.             PositionDialog('ALRT', largeAlert);
  172.             StopAlert(largeAlert, 0L);        /* display error alert */
  173.             break;
  174.         default:
  175.             gCanSavePrefs=TRUE;                /* can save prefs to disk later if needed */
  176.             break;
  177.     }
  178. }
  179.  
  180. int OpenPrefsFile(int *prefsFileID)
  181. {
  182.     int                thisFile;
  183.     OSErr            isHuman;
  184.     int                vRefNum;
  185.     long            dirID;
  186.     FSSpec            prefsFile;
  187.     FInfo            prefsInfo;
  188.     Boolean            newPrefs;
  189.     unsigned char    *name=PREFS_FILE_NAME;
  190.     
  191.     newPrefs=FALSE;
  192.     /* find vRefNum and dirID of preferences folder, creating it if necessary */
  193.     isHuman=FindFolder(kOnSystemDisk, 'pref', kCreateFolder, &vRefNum, &dirID);
  194.     
  195.     if (isHuman!=noErr)        /* screwed up already?!? */
  196.         return prefs_cantOpenPrefsErr;
  197.     if (gHasFSSpecs)
  198.     {
  199.         isHuman=FSMakeFSSpec(vRefNum, dirID, name, &prefsFile);    /* make FSSpec out of it */
  200.         if (isHuman!=noErr)
  201.         {
  202.             if (isHuman==fnfErr)    /* FSSpec is valid, but prefs file does not exist */
  203.             {
  204.                 isHuman=FSpCreate(&prefsFile, CREATOR, PREFS_TYPE, 0);    /* so create it */
  205.                 if (isHuman!=noErr)                                        /* or not */
  206.                     return prefs_cantCreatePrefsErr;
  207.                 newPrefs=TRUE;        /* signal that prefs file is new */
  208.             }
  209.             else return prefs_cantOpenPrefsErr;
  210.         }
  211.         isHuman=FSpOpenDF(&prefsFile, fsRdWrPerm, &thisFile);    /* open prefs file */
  212.         *prefsFileID=thisFile;        /* store file reference number */
  213.         if (isHuman!=noErr)
  214.             return prefs_cantOpenPrefsErr;
  215.     }
  216.     else
  217.     {
  218.         /* try to open prefs file */
  219.         isHuman=HOpen(vRefNum, dirID, name, fsRdWrPerm, &thisFile);
  220.         *prefsFileID=thisFile;
  221.         if (isHuman!=noErr)
  222.         {
  223.             if (isHuman==fnfErr)    /* prefs file does not exist */
  224.             {
  225.                 /* ...so create it */
  226.                 if (HCreate(vRefNum, dirID, name, CREATOR, PREFS_TYPE)!=noErr)
  227.                     return prefs_cantCreatePrefsErr;
  228.                 prefsInfo.fdType=PREFS_TYPE;
  229.                 prefsInfo.fdCreator=CREATOR;
  230.                 prefsInfo.fdFlags=0;
  231.                 prefsInfo.fdLocation.h=prefsInfo.fdLocation.v=0;
  232.                 prefsInfo.fdFldr=0;
  233.                 
  234.                 /* set file info of newly created prefs file */
  235.                 if (HSetFInfo(vRefNum, dirID, name, &prefsInfo)!=noErr)
  236.                     return prefs_cantCreatePrefsErr;
  237.                 
  238.                 /* NOW open the prefs file */
  239.                 isHuman=HOpen(vRefNum, dirID, name, fsRdWrPerm, &thisFile);
  240.                 *prefsFileID=thisFile;        /* store file reference number */
  241.                 if (isHuman!=noErr)
  242.                     return prefs_cantOpenPrefsErr;
  243.                 newPrefs=TRUE;                /* signal that prefs file is new */
  244.             }
  245.             else return prefs_cantOpenPrefsErr;
  246.         }
  247.     }
  248.     if (newPrefs)
  249.         return SetupNewPrefsFile(*prefsFileID);        /* needs initial setup if new */
  250.     
  251.     return prefs_allsWell;
  252. }
  253.  
  254. int SetupNewPrefsFile(int prefsFileID)
  255. /* this writes the prefs version number to the newly created prefs file, so we can
  256.    tell if the prefs file was created by a later version of the program and is
  257.    therefore in a format that we don't support -- forward compatability!  what
  258.    a concept! */
  259. {
  260.     long            count;
  261.     int                temp;
  262.     
  263.     gPrefsFilePos=2L;
  264.     if (SetEOF(prefsFileID, 2L)!=noErr)    /* set length of prefs file to 2 */
  265.         return prefs_diskWriteErr;
  266.     
  267.     SetFPos(prefsFileID, 1, 0L);
  268.     temp=PREFS_HEADER_VERSION;            /* get the prefs version (hardcoded) */
  269.     count=2L;
  270.     if (FSWrite(prefsFileID, &count, &temp)!=noErr)        /* write prefs version */
  271.         return prefs_diskWriteErr;        
  272.     
  273.     return Virgin(prefsFileID);            /* be gentle; it's our first time */
  274. }
  275.  
  276. void ClosePrefsFile(int prefsFileID)
  277. {
  278.     FSClose(prefsFileID);                /* close file on disk */
  279.     FlushVol(0L, kOnSystemDisk);        /* flush volume to write out new info */
  280. }
  281.  
  282. int GetNextPrefs(int prefsFileID)
  283. {
  284.     OSErr        isHuman;
  285.     long        count;
  286.     
  287.     count=sizeof(thePrefs);
  288.     isHuman=FSRead(prefsFileID, &count, &thePrefs);        /* get next prefs struct */
  289.     if (isHuman==eofErr)    /* no more left */
  290.         return prefs_noMorePrefsErr;
  291.     if (isHuman!=noErr)        /* some other error */
  292.         return prefs_diskReadErr;
  293.     
  294.     return prefs_allsWell;
  295. }
  296.  
  297. int SavePrefs(int prefsFileID)
  298. {
  299.     long        oldEOF;
  300.     long        count;
  301.     
  302.     GetEOF(prefsFileID, &oldEOF);
  303.     if (gPrefsFilePos>=oldEOF)        /* add new prefs struct onto end of prefs file */
  304.     {
  305.         if (SetEOF(prefsFileID, oldEOF+sizeof(thePrefs))!=noErr)
  306.             return prefs_diskWriteErr;
  307.     }
  308.     
  309.     SetFPos(prefsFileID, 1, gPrefsFilePos);        /* set position inside prefs file */
  310.     count=sizeof(thePrefs);
  311.     /* write prefs struct and return appropriate error code */
  312.     return (FSWrite(prefsFileID, &count, &thePrefs)!=noErr) ?
  313.         prefs_diskWriteErr : prefs_allsWell;
  314. }
  315.  
  316. int CheckVersion(int prefsFileID)
  317. {
  318.     OSErr        isHuman;
  319.     long        count;
  320.     int            temp;
  321.     
  322.     count=2L;
  323.     isHuman=FSRead(prefsFileID, &count, &temp);        /* get prefs version */
  324.     if (isHuman!=noErr)
  325.         return prefs_diskReadErr;
  326.     if (temp>PREFS_HEADER_VERSION)                    /* too new */
  327.         return prefs_versionNotSupportedErr;
  328.     if (temp<PREFS_HEADER_VERSION)                    /* old; overwrite */
  329.         return SetupNewPrefsFile(prefsFileID);
  330.     
  331.     return prefs_allsWell;
  332. }
  333.  
  334. int GetFileID(void)
  335. {
  336.     ParamBlockRec    pb;
  337.     
  338.     pb.fileParam.ioCompletion=0L;
  339.     pb.fileParam.ioNamePtr=CurApName;
  340.     pb.fileParam.ioVRefNum=0;
  341.     pb.fileParam.ioFVersNum=0;
  342.     pb.fileParam.ioFDirIndex=0;
  343.     if (PBGetFInfo(&pb, FALSE)!=noErr)
  344.         return prefs_diskReadErr;
  345.     
  346.     gFileID=pb.fileParam.ioFlNum;
  347. }
  348.  
  349. int CheckFileID(void)
  350. {
  351.     /* compare file ID in current prefs struct to application's file ID */
  352.     return (thePrefs.fileID==gFileID) ? prefs_allsWell : prefs_IDNotMatchErr;
  353. }
  354.  
  355. int Virgin(int prefsFileID)
  356. {
  357.     int            err;
  358.     
  359.     DefaultPrefs();
  360.     CopyGlobalsToPrefs();
  361.     err=SavePrefs(prefsFileID);
  362.     if (err!=prefs_allsWell)
  363.         return err;
  364.     DoSound(sound_virgin, TRUE);
  365.     GetRegistration();
  366.     CopyGlobalsToPrefs();
  367.     err=SavePrefs(prefsFileID);
  368.     
  369.     return (err==prefs_allsWell) ? prefs_virginErr : err;
  370. }
  371.  
  372. void DefaultPrefs(void)
  373. {
  374.     unsigned char        *bob="\pBob";
  375.     
  376.     Mymemcpy(gMyName, bob, bob[0]+1);
  377.     gMyOrg[0]=0x00;
  378.     gSoundToggle=gWhichPict=0xFF;
  379.     gIsReversed=0x00;
  380.     gLastWipe=-1;
  381.     gWipeStatus=kEffectsOnly;
  382. }
  383.  
  384. void CopyGlobalsToPrefs(void)
  385. {
  386.     Mymemset(&thePrefs, 0, sizeof(thePrefs));
  387.     if (gMyName[0]>0x27)
  388.         gMyName[0]=0x27;
  389.     if (gMyOrg[0]>0x27)
  390.         gMyOrg[0]=0x27;
  391.     Mymemcpy(thePrefs.regname, gMyName, gMyName[0]+1);
  392.     Mymemcpy(thePrefs.regorg, gMyOrg, gMyOrg[0]+1);
  393.     thePrefs.sound=gSoundToggle;
  394.     thePrefs.isreversed=gIsReversed;
  395.     thePrefs.isfirstpict=gWhichPict;
  396.     thePrefs.lastwipe=gLastWipe;
  397.     thePrefs.wipestatus=gWipeStatus;
  398.     thePrefs.fileID=gFileID;
  399. }
  400.  
  401. void CopyPrefsToGlobals(void)
  402. {
  403.     Mymemcpy(gMyName, thePrefs.regname, thePrefs.regname[0]+1);
  404.     Mymemcpy(gMyOrg, thePrefs.regorg, thePrefs.regorg[0]+1);
  405.     gSoundToggle=thePrefs.sound;
  406.     gIsReversed=thePrefs.isreversed;
  407.     gWhichPict=thePrefs.isfirstpict;
  408.     gLastWipe=thePrefs.lastwipe;
  409.     gWipeStatus=thePrefs.wipestatus;
  410. }
  411.  
  412. void GetRegistration(void)
  413. {
  414.     DialogPtr        theDlog;
  415.     int                itemSelected = 0;
  416.     int                newleft;
  417.     int                newtop;
  418.     int                itemType;
  419.     Handle            item;
  420.     Rect            box;
  421.     
  422.     theDlog = GetNewDialog(personalDialog, 0L, (WindowPtr)-1L);
  423.     newleft = screenBits.bounds.left + (((screenBits.bounds.right -
  424.                 screenBits.bounds.left) - (theDlog->portRect.right -
  425.                 theDlog->portRect.left)) / 2);
  426.     newtop = screenBits.bounds.top + (((screenBits.bounds.bottom -
  427.                 screenBits.bounds.top) - (theDlog->portRect.bottom -
  428.                 theDlog->portRect.top)) / 2);
  429.     if(newtop < 15)
  430.         newtop = 15;
  431.     GetDItem(theDlog, 1, &itemType, &item, &box);
  432.     InsetRect(&box, -4, -4);
  433.     SetDItem(theDlog, 8, userItem, OutlineDefaultButton, &box);
  434.     ParamText(APPLICATION_NAME, "\p", "\p", "\p");
  435.     
  436.     MoveWindow(theDlog, newleft, newtop, TRUE);
  437.     ShowWindow(theDlog);
  438.     while(itemSelected != 1)
  439.     {
  440.         ModalDialog(0L, &itemSelected);
  441.     }
  442.     GetDItem(theDlog,4,&itemType,&item,&box);
  443.     GetIText(item,&gMyName);
  444.     
  445.     GetDItem(theDlog,5,&itemType,&item,&box);
  446.     GetIText(item,&gMyOrg);
  447.  
  448.     if (gMyName[0]==0x00)
  449.         DefaultPrefs();
  450.  
  451.     HideWindow(theDlog);
  452.     DisposeDialog(theDlog);
  453. }
  454.